#include "FOSGLFire.h"

CFOSGLFire::CFOSGLFire(void)
{
}

CFOSGLFire::~CFOSGLFire(void)
{
}

void CFOSGLFire::InitFire(){

	int p;

	FireParticleCount = 10000;
	SmokeParticleCount = 100;

	ActivateFirePerFrame = 40;
	ActivateSmokePerFrame = 1;

	FireParticles = new PARTICLE[FireParticleCount];
	SmokeParticles = new PARTICLE[SmokeParticleCount];

	for (p=0;p<FireParticleCount;p++){

		FireParticles[p].Active = false;

	}
	for (p=0;p<SmokeParticleCount;p++){

		SmokeParticles[p].Active = false;

	}

}

void CFOSGLFire::PrepareFire(){

	int p;

	for (p=0;p<FireParticleCount;p++){

		// We move the speed towards the target speed by 1/20 (5%)
		FireParticles[p].sX+= (FireParticles[p].tX - FireParticles[p].sX) / 10.0f;
		FireParticles[p].sY+= (FireParticles[p].tY - FireParticles[p].sY) / 20.0f;
		FireParticles[p].sZ+= (FireParticles[p].tZ - FireParticles[p].sZ) / 10.0f;
		// Then we adjust the position of the particle by the new speed
		FireParticles[p].X+= FireParticles[p].sX;
		FireParticles[p].Y+= FireParticles[p].sY;
		FireParticles[p].Z+= FireParticles[p].sZ;

		// Adjust the size of the particles
		FireParticles[p].Size-= 0.002f;
		if(FireParticles[p].Size < 0.0f){
			FireParticles[p].Active = false;
		}

		// Adjust the colour of the particles
		FireParticles[p].R -= 0.01f;
		FireParticles[p].G -= 0.03f;

		if(FireParticles[p].R < 0.1f) FireParticles[p].R = 0.1f;
		if(FireParticles[p].G < 0.1f) FireParticles[p].G = 0.0f;

		// And finally the age check
		FireParticles[p].Age++;
		if(FireParticles[p].Age > FireParticles[p].MaxAge){
			FireParticles[p].Active = false;
		}
	
	}


	for (p=0;p<SmokeParticleCount;p++){

		SmokeParticles[p].Active = false;

	}


}

void CFOSGLFire::ActivateFireParticles(){

	int p;

	for (p=0;p<FireParticleCount;p++){

		if(!FireParticles[p].Active){

			// Start the particle at 0,0,0 origin
			FireParticles[p].X = (((float)((rand() % 50) + 1)) / 100.0f) - 0.25f;
			FireParticles[p].Y = 0.0f;
			FireParticles[p].Z = (((float)((rand() % 50) + 1)) / 100.0f) - 0.25f;

			// Set The Target Speed of the particles
			FireParticles[p].tX = 0.0f;
			FireParticles[p].tY = 0.01f;
			FireParticles[p].tZ = 0.0f;
			
			// The following lines set a random speed value
			FireParticles[p].sX = (((float)((rand() % 30) + 1)) / 1000.0f) - 0.015f;
			FireParticles[p].sY = (((float)((rand() % 50) + 1)) / 1000.0f);
			FireParticles[p].sZ = (((float)((rand() % 30) + 1)) / 1000.0f) - 0.015f;

			// We also activate the particle
			FireParticles[p].Active = true;
			// Set it's Age to zero
			FireParticles[p].Age = 0;
			// We also assign a max age to the particles
			FireParticles[p].MaxAge = 300;

			// Set the particle Colour
			FireParticles[p].R = 0.7f;
			FireParticles[p].G = 0.6f;
			FireParticles[p].B = 0.0f;

			// Set the Particle Size
			FireParticles[p].Size = (((float)((rand() % 15))) / 100.0f);


			return;
		}
	}
}

void CFOSGLFire::ActivateSmokeParticles(){

	int p;

	for (p=0;p<SmokeParticleCount;p++){

		if(!SmokeParticles[p].Active){


			return;
		}
	}
}


void CFOSGLFire::RenderFire(){

	for(int i=0;i<ActivateFirePerFrame;i++){
		ActivateFireParticles();
	}
	for(int i=0;i<ActivateSmokePerFrame;i++){
		ActivateSmokeParticles();
	}
	
	
	PrepareFire();

	int p;

	GLfloat fogColor[4]= {0.0f, 0.0f, 0.0f, 0.5f};

	glFogi(GL_FOG_MODE, GL_LINEAR);		// Fog Mode
	glFogfv(GL_FOG_COLOR, fogColor);			// Set Fog Color
	glFogf(GL_FOG_DENSITY, 0.35f);				// How Dense Will The Fog Be
	glHint(GL_FOG_HINT, GL_DONT_CARE);			// Fog Hint Value
	glFogf(GL_FOG_START, 1.0f);				// Fog Start Depth
	glFogf(GL_FOG_END, 2.0f);				// Fog End Depth
	glEnable(GL_FOG);					// Enables GL_FOG



	GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f }; 
	GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };
	GLfloat LightPosition[]={ 0.0f, 
							  0.1f, 
							  0.0f, 
							  1.0f };

	glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
	glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
	glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);
	glEnable(GL_LIGHT1);
	glEnable(GL_LIGHTING);

	//Render the floor
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, tFloor);
	glDisable(GL_BLEND);

	
	//	glColor4f(0.5f, 0.5f, 0.5f, 0.5f);
		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

		for (int y=0; y<20; y++){		
			for (int x=0; x<20; x++){
				glPushMatrix();
				glTranslatef(-5.0f, 0.0f, 5.0f);
				glTranslatef((float)x / 2, 0.0f, -(float)y / 2);
				glBegin(GL_QUADS);
					glNormal3f(0.0f, 1.0f, 0.0f);	glTexCoord2f(0.0f, 0.0f);		glVertex3f( 0.0f, 0.0f,  0.0f);
					glNormal3f(0.0f, 1.0f, 0.0f);	glTexCoord2f(1.0f, 0.0f);		glVertex3f( 0.5f, 0.0f,  0.0f);
					glNormal3f(0.0f, 1.0f, 0.0f);	glTexCoord2f(1.0f, 1.0f);		glVertex3f( 0.5f, 0.0f, -0.5f);
					glNormal3f(0.0f, 1.0f, 0.0f);	glTexCoord2f(0.0f, 1.0f);		glVertex3f( 0.0f, 0.0f, -0.5f);
				glEnd();
				glPopMatrix();
			}
		}
	


	glDisable(GL_LIGHTING);
	glDisable(GL_FOG);

	// Enable textures and bind our particle texture
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, tFire);

	// Disable Depth testing.
	glDisable(GL_DEPTH_TEST);

	// Enable blending
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_COLOR,GL_ONE);

	for(p=0; p<FireParticleCount; p++){

		if(FireParticles[p].Active){
			glColor4f(FireParticles[p].R, FireParticles[p].G, FireParticles[p].B, 1.0f);

			glPushMatrix();

				glTranslatef(FireParticles[p].X, FireParticles[p].Y, FireParticles[p].Z);

			//	glRotatef(-Rotation, 0.0f, 1.0f, 0.0f);

				glNormal3f(0.0f, 0.0f, 1.0f);

				glBegin(GL_QUADS);
					glTexCoord2f(0.0f, 0.0f);		glVertex3f(-FireParticles[p].Size, -FireParticles[p].Size, 0.0f);
					glTexCoord2f(1.0f, 0.0f);		glVertex3f(FireParticles[p].Size, -FireParticles[p].Size, 0.0f);
					glTexCoord2f(1.0f, 1.0f);		glVertex3f(FireParticles[p].Size, FireParticles[p].Size, 0.0f);
					glTexCoord2f(0.0f, 1.0f);		glVertex3f(-FireParticles[p].Size, FireParticles[p].Size, 0.0f);
				glEnd();

			glPopMatrix();
		}
	}

	glEnable(GL_DEPTH_TEST);

}



GLuint CFOSGLFire::LoadBitmapTexture(char * FileName)					// Creates Texture From A Bitmap File
{
	HBITMAP hBMP;														// Handle Of The Bitmap
	BITMAP	BMP;	// Bitmap Structure
	GLuint texid;

	glGenTextures(1, &texid);   // Create The Texture


	hBMP=(HBITMAP)LoadImage(GetModuleHandle(NULL), FileName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE );

	if (!hBMP)															// Does The Bitmap Exist?
		return FALSE;													// If Not Return False

	GetObject(hBMP, sizeof(BMP), &BMP);									// Get The Object
																		// hBMP:        Handle To Graphics Object
																		// sizeof(BMP): Size Of Buffer For Object Information
																		// &BMP:        Buffer For Object Information

	glPixelStorei(GL_UNPACK_ALIGNMENT, 4);								// Pixel Storage Mode (Word Alignment / 4 Bytes)

	// Typical Texture Generation Using Data From The Bitmap
	glBindTexture(GL_TEXTURE_2D, texid);								// Bind To The Texture ID
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);	// Linear Min Filter
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);	// Linear Mag Filter
	glTexImage2D(GL_TEXTURE_2D, 0, 3, BMP.bmWidth, BMP.bmHeight, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, BMP.bmBits);

	DeleteObject(hBMP);													// Delete The Object

	return texid;														// Loading Was Successful
}

